#pragma once
#include "../common/dispatcher.hpp"
#include "../client/rpc_client.hpp"
#include "rpc_router.hpp"
#include "rpc_registry.hpp"
#include "rpc_topic.hpp"

namespace rcrpc {
    namespace server {
        // 注册中心服务器，只需要针对服务注册与发现请求进行处理即可
        class RegistryServer {
            public:
                using ptr = std::shared_ptr<RegistryServer>;
                RegistryServer(int port): 
                    _pd_manager(std::make_shared<PDManager>()),
                    _dispatcher(std::make_shared<Dispatcher>())
                {
                    auto service_cb = std::bind(&PDManager::onServiceRequest, _pd_manager.get(),
                        std::placeholders::_1, std::placeholders::_2);
                    _dispatcher->registerHandler<ServiceRequest>(MType::REQ_SERVICE, service_cb);

                    // 已经设置监听了，所有地址，不需要再设置了
                    _server = ServerFactory::create(port); 
                    auto msg_cb = std::bind(&Dispatcher::onMessage, _dispatcher.get(),
                        std::placeholders::_1, std::placeholders::_2);
                    _server->setMessageCallback(msg_cb);

                    auto close_cb = std::bind(&RegistryServer::onConnShutdown, this, std::placeholders::_1);
                    _server->setCloseCallback(close_cb);
                }
                void start() {
                    _server->start();
                }
            private:
                void onConnShutdown(const BaseConnection::ptr conn) {
                    _pd_manager->onConnShutdown(conn);
                }
            private:
                PDManager::ptr _pd_manager;
                Dispatcher::ptr _dispatcher;
                BaseServer::ptr _server;
        };


        // 在不使注册中心的服务器的情况下，RPCServer直接和RPCClinet相互连接
        class RPCServer {
            public:
                using ptr = std::shared_ptr<RPCServer>;
                // rpc-server端有两套地址信息：
                // 1. rpc服务提供端地址信息--必须是rpc服务对外访问地址（云服务器--监听地址和访问地址不同）
                // 2. 注册中心服务端地址信息 -- 启用服务注册后， 连接注册中心进行服务注册用
                RPCServer(const Address& access_addr,
                    bool enableRegistry = false,
                    const Address& registry_client_addr = Address()) :
                    _enableRegistry(enableRegistry),
                    _access_addr(access_addr),
                    _router(std::make_shared<RpcRouter>()),
                    _dispatcher(std::make_shared<Dispatcher>())
                    {
                        if (_enableRegistry) {
                            _registry_client = std::make_shared<client::RegistryClient>(
                                    registry_client_addr.first, registry_client_addr.second
                            );
                        }

                        auto service_cb = std::bind(&RpcRouter::onRpcRequest, _router.get(),
                        std::placeholders::_1, std::placeholders::_2);
                        _dispatcher->registerHandler<RpcRequest>(MType::REQ_RPC, service_cb);

                        // 已经设置监听了，所有地址，不需要再设置了
                        _server = ServerFactory::create(_access_addr.second); 
                        auto msg_cb = std::bind(&Dispatcher::onMessage, _dispatcher.get(),
                            std::placeholders::_1, std::placeholders::_2);
                        _server->setMessageCallback(msg_cb);
                     }

                    void registerMethod(const ServiceDescribe::ptr &service) {
                        if (_enableRegistry) {
                            // 注册到服务中心
                            _registry_client->registerMethod(service->method(), _access_addr); 
                        }
                        // 注册到服务端的 RpcRouter 里 ServiceManager 中
                        _router->registerMethod(service);
                    }
                    void start() {
                        _server->start();
                    }

            private:
                bool _enableRegistry;
                Address _access_addr;
                client::RegistryClient::ptr _registry_client;
                RpcRouter::ptr _router;
                Dispatcher::ptr _dispatcher;
                BaseServer::ptr _server;

        };

        class TopicServer {
            public:
                using ptr = std::shared_ptr<TopicServer>;
                TopicServer(int port): 
                    _topic_manager(std::make_shared<TopicManager>()),
                    _dispatcher(std::make_shared<Dispatcher>())
                {
                    auto topic_cb = std::bind(&TopicManager::onTopicRequest, _topic_manager.get(),
                        std::placeholders::_1, std::placeholders::_2);
                    _dispatcher->registerHandler<TopicRequest>(MType::REQ_TOPIC, topic_cb);

                    // 已经设置监听了，所有地址，不需要再设置了
                    _server = ServerFactory::create(port); 
                    auto msg_cb = std::bind(&Dispatcher::onMessage, _dispatcher.get(),
                        std::placeholders::_1, std::placeholders::_2);
                    _server->setMessageCallback(msg_cb);

                    auto close_cb = std::bind(&TopicServer::onConnShutdown, this, std::placeholders::_1);
                    _server->setCloseCallback(close_cb);
                }
                void start() {
                    _server->start();
                }
            private:
                void onConnShutdown(const BaseConnection::ptr conn) {
                    _topic_manager->onShutdown(conn);
                }
            private:
                TopicManager::ptr _topic_manager;
                Dispatcher::ptr _dispatcher;
                BaseServer::ptr _server;
        };

    }
}